#include "ssd1327.h"

#include "zf_gpio.h"
#include "zf_delay.h"
#include "zf_spi.h"

// u8g2对象，有关u8g2的都需要它
u8g2_t xdata u8g2;

void HAL_SPI_Transmit(uint8_t *Mem, uint16_t MemSize)
{
	uint16_t i = 0;
	for (i = 0; i < MemSize; i++)
	{
		SPDAT = *(Mem + i);
		while (!SPIF)
			;
		SPIF = 1; // 清SPIF标志
		WCOL = 1; // 清WCOL标志
	}
}

static uint8_t u8x8_byte_4wire_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
	/* u8g2/u8x8 will never send more than 32 bytes between START_TRANSFER and END_TRANSFER */
	switch (msg)
	{
	case U8X8_MSG_BYTE_SEND:
		HAL_SPI_Transmit(arg_ptr, arg_int);
		break;
	case U8X8_MSG_BYTE_INIT: /*初始化操作*/
		// HAL_SPI_Init();
		break;
	case U8X8_MSG_BYTE_SET_DC:
		OLED_DC_Pin = arg_int;
		break;
	case U8X8_MSG_BYTE_START_TRANSFER: /*数据传输完成之后将CS引脚使能*/
		OLED_CS_Pin = ON;
		break;
	case U8X8_MSG_BYTE_END_TRANSFER: /*数据传输完成之后将CS引脚拉起*/
		OLED_CS_Pin = OFF;
		break;

	default:
		return 0;
	}

	return 1;
}

static uint8_t u8x8_stc32_gpio_and_delay(U8X8_UNUSED u8x8_t *u8x8, U8X8_UNUSED uint8_t msg, U8X8_UNUSED uint8_t arg_int, U8X8_UNUSED void *arg_ptr)
{
	switch (msg)
	{
	case U8X8_MSG_GPIO_AND_DELAY_INIT:
		delay_ms(1);
		break;
	case U8X8_MSG_DELAY_MILLI:
		delay_ms(arg_int);

		break;
	case U8X8_MSG_GPIO_I2C_CLOCK:
		break;

	case U8X8_MSG_GPIO_I2C_DATA:
		break;

	case U8X8_MSG_GPIO_CS: /*this cmd is not use*/
		OLED_CS_Pin = arg_int;
		break;
	case U8X8_MSG_GPIO_DC:
		OLED_DC_Pin = arg_int;
		break;
	case U8X8_MSG_GPIO_RESET:
		OLED_RST_Pin = arg_int;
		break;
	}
	return 1;
}

void OLED_Init(void)
{
	gpio_mode(P0_1, GPIO);
	gpio_mode(P0_0, GPIO);
	gpio_mode(P4_6, GPIO);

	u8g2_Setup_ssd1327_ws_128x128_f(&u8g2, U8G2_R2, u8x8_byte_4wire_hw_spi, u8x8_stc32_gpio_and_delay);
	OLED_DC_Pin = 0;
	u8g2_InitDisplay(&u8g2);
	u8g2_SetPowerSave(&u8g2, 0);

	// 清屏
	u8g2_ClearDisplay(&u8g2);
	// 设置字体
	u8g2_SetFont(&u8g2, u8g2_font_amstrad_cpc_extended_8r);
}

// 以下是老驱动，现在采用u8g2驱动
#if 0
#include "oledfont.h"
void OLED_WriteByte(uint8 _data, uint8 _switch)
{
    if (_switch == OLED_DATA)
    {
        OLED_DC_Pin = OFF;
    }
    else
    {
        OLED_DC_Pin = ON;
    }
    OLED_CS_Pin = ON;
    spi_mosi(_data);
    OLED_CS_Pin = OFF;
    OLED_DC_Pin = OFF;
}

void OLED_Init(void)
{
    gpio_mode(P0_1, GPIO);
    gpio_mode(P0_0, GPIO);
    gpio_mode(P4_6, GPIO);
    OLED_CS_Pin = OFF;
    OLED_DC_Pin = OFF;
    OLED_RST_Pin = ON;
    delay_ms(100);
    OLED_RST_Pin = OFF;

    OLED_WriteByte(0xAE, OLED_CMD);// Set display off
    OLED_WriteByte(0xA0, OLED_CMD);// Set re-map
    if (DispDire)
    {//设置显示方向
        OLED_WriteByte(0x66, OLED_CMD);
    }
    else
    {
        OLED_WriteByte(0x55, OLED_CMD);
    }
    OLED_WriteByte(0xA1,OLED_CMD);//Set display start line
	OLED_WriteByte(0x00,OLED_CMD);
    OLED_WriteByte(0xA2,OLED_CMD);//Set display offset
	OLED_WriteByte(0x00,OLED_CMD);
	OLED_WriteByte(0xA4,OLED_CMD);//Normal Display
	OLED_WriteByte(0xA8,OLED_CMD);//Set multiplex ratio
	OLED_WriteByte(0x7F,OLED_CMD);
	OLED_WriteByte(0xAB,OLED_CMD);//Function Selection A
	OLED_WriteByte(0x01,OLED_CMD);//Enable internal VDD regulator
	OLED_WriteByte(0x81,OLED_CMD);//Set contrast
	OLED_WriteByte(0x77,OLED_CMD);
	OLED_WriteByte(0xB1,OLED_CMD);//Set Phase Length
	OLED_WriteByte(0x31,OLED_CMD);
	OLED_WriteByte(0xB3,OLED_CMD);//Set Front Clock Divider /Oscillator Frequency
	OLED_WriteByte(0xB1,OLED_CMD);
    OLED_WriteByte(0xB5,OLED_CMD);//
    OLED_WriteByte(0x03,OLED_CMD);//0X03 enable
	OLED_WriteByte(0xB6,OLED_CMD);//Set Second pre-charge Period
	OLED_WriteByte(0x0D,OLED_CMD);
	OLED_WriteByte(0xBC,OLED_CMD);//Set Pre-charge voltage
	OLED_WriteByte(0x07,OLED_CMD);
	OLED_WriteByte(0xBE,OLED_CMD);//Set VCOMH
	OLED_WriteByte(0x07,OLED_CMD);
	OLED_WriteByte(0xD5,OLED_CMD);//Function Selection B
	OLED_WriteByte(0x02,OLED_CMD);//Enable second pre-charge
	OLED_Clear(0,0,128,128,0x00);//清屏
	OLED_WriteByte(0xAf,OLED_CMD);//Display on
}

void Column_Address(uint8 a, uint8 b)
{
	OLED_WriteByte(0x15,OLED_CMD);			    // Set Column Address
	OLED_WriteByte(a,OLED_CMD);				//   Default => 0x00
	OLED_WriteByte(b,OLED_CMD);				//   Default => 0x77
}

void Row_Address(uint8 a, uint8 b)
{
	OLED_WriteByte(0x75,OLED_CMD);			// Set Row Address
	OLED_WriteByte(a,OLED_CMD);				//   Default => 0x00
	OLED_WriteByte(b,OLED_CMD);				//   Default => 0x3F
}

void OLED_Clear(uint8 x1,uint8 y1,uint8 x2,uint8 y2,uint8 color)
{
    uint8 i,m;
    x1/=2;x2/=2;
    Column_Address(x1,x2-1);
	Row_Address(y1,y2-1);
    for (m=0;m<y2-y1;m++) 
	{ 
		for (i=0;i<x2-x1;i++)
		{
			 OLED_WriteByte(color,OLED_DATA);
		}
	}
}
void OLED_ShowChar(uint8 x,uint8 y,uint8 _char,uint8 sizey)
{
	uint8 i,j,c,k;
	uint8 data1,data2,DATA1=0;
	c=_char-' ';
	for(i=0;i<sizey/8;i++)
	{
	  Column_Address(x/2,x/2+sizey/4-1);//设置列地址
	  Row_Address(y+i*8,y+i*8+7);//设置行地址
		for(j=0;j<sizey/4;j++)
		{
			if(sizey==16)//8x16 ASCII码
			{
				data1=F8X16[c][2*j+i*sizey/2+0];
				data2=F8X16[c][2*j+i*sizey/2+1];
			}
			else if(sizey==24)//12x24 ASCII码
			{
				data1=F12X24[c][2*j+i*sizey/2+0];
				data2=F12X24[c][2*j+i*sizey/2+1];

			}
			else if(sizey==32)//16x32 ASCII码
			{
				data1=F16X32[c][2*j+i*sizey/2+0];
				data2=F16X32[c][2*j+i*sizey/2+1];
			}
			for(k=0;k<8;k++)
			{
				if(data1&(0x01<<k))
				{
					DATA1=0xf0;
				}
				if(data2&(0x01<<k))
				{
					DATA1|=0x0f;
				}
				OLED_WriteByte(DATA1,OLED_DATA);
				DATA1=0;
			}
		}
	}
}

void OLED_ShowString(uint8 x,uint8 y,uint8 *dp,uint8 sizey)
{
	while(*dp!='\0')
	{
	  OLED_ShowChar(x,y,*dp,sizey);
		dp++;
		x+=sizey/2;
	}
}
#endif
